﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
using System.Linq;

public class WalkerScript : MonoBehaviour
{

    public Action OnFinishWalk;
    public Action OnBetweenWalk;

    private BaseItemScript _baseItem;
    private float _speed = 5f;
    private Vector3 _targetPosition;

    private bool _isWalking = false;
    private bool _pathAcomplete = false;
    private bool _pathBcomplete = false;

    public bool EnableGizmos = false;

    public void SetData(BaseItemScript baseItem)
    {
        this._baseItem = baseItem;
        this._speed = baseItem.itemData.configuration.speed;
    }

    void Update()
    {
        WalkPath();
        if (!this._isWalking)
        {
            return;
        }

        this.WalkUpdate();
    }

    /// <summary>
    /// Update on walker. which call every frame if _isWalking is true
    /// </summary>
    public void WalkUpdate()
    {
        float frameDistance = Time.deltaTime * _speed;
        float interpolationValue = frameDistance / (_targetPosition - transform.localPosition).magnitude;
        transform.localPosition = Vector3.Lerp(transform.localPosition, _targetPosition, interpolationValue);

        if (transform.localPosition == this._targetPosition)
        {
            this._WalkNextNode();
        }
    }

    /// <summary>
    /// Finishs the walk.
    /// </summary>
    public void FinishWalk()
    {
        //		Debug.Log ("FinishWalk");
        this._baseItem.SetState(Common.State.IDLE);

        this._isWalking = false;
        this._targetPosition = transform.position;

        if (this.OnFinishWalk != null)
        {
            //Debug.Log(OnFinishWalk.Method);
            //Debug.Log(OnFinishWalk.Target);
            this.OnFinishWalk.Invoke();
        }

        OnBetweenWalk = null;
    }

    /// <summary>
    /// Moves to position.
    /// </summary>
    /// <param name="position">Position.</param>
    public void MoveToPosition(Vector3 position)
    {
        this._isWalking = true;
        this._targetPosition = position;
        this._baseItem.LookAt(position);
    }

    /// <summary>
    /// Walks to position.
    /// </summary>
    /// <param name="position">Position.</param>
    public void WalkToPosition(Vector3 position)
    {
        this.CancelWalk();
        FindPath(position);
        return;
    }
    void FindPath(Vector3 position)
    {

        var startPosition = GridManager.instance.SnapToGrid(this.transform.position);
        //绕路
        Action<List<Vector3>> pathWithWall = (List<Vector3> path) =>
        {
            GridManager.Path patha = new GridManager.Path();
            patha.nodes = path.ToArray();

            path1 = patha;
            _pathAcomplete = true;
        };
        //穿墙
        Action<List<Vector3>> pathCrossWall = (List<Vector3> path) =>
        {
            GridManager.Path pathb = new GridManager.Path();
            pathb.nodes = path.ToArray();

            path2 = pathb;
            _pathBcomplete = true;
        };
        //GridManager.instance.GetPathSync(this.transform.position, position, false, pathWithWall);
        //GridManager.instance.GetPathSync(this.transform.position, position, true, pathCrossWall);
        GridManager.instance.GetPathSync(startPosition, position, false, pathWithWall);
        GridManager.instance.GetPathSync(startPosition, position, true, pathCrossWall);
    }

    private GridManager.Path _path;
    private int _currentNodeIndex;

    void WalkPath()
    {
        if (SceneManager.instance.gameMode == Common.GameMode.NORMAL)
            WalkNormal();
        if (SceneManager.instance.gameMode == Common.GameMode.ATTACK)
            WalkAttack();

        void WalkNormal()
        {
            if (path2 != null && !_isWalking && _baseItem.state == Common.State.IDLE && _pathAcomplete)
            {
                this.WalkThePath(path2);
                _pathAcomplete = false;
            }
        }
        void WalkAttack()
        {
            if (path1 != null && path2 != null && !_isWalking && _baseItem.state == Common.State.IDLE && _pathAcomplete && _pathBcomplete)
            {
                float difference = path1.GetDistanceAlongPath() - path2.GetDistanceAlongPath();
                if (difference > 0 && difference <= 20)
                {
                    this.WalkThePath(path1);
                    _pathAcomplete = false;
                }
                else
                {
                    this.WalkThePath(path2);
                    _pathBcomplete = false;
                }
            }
        }
    }
    /// <summary>
    /// Walks the path.
    /// </summary>
    /// <param name="path">Path.</param>
    void WalkThePath(GridManager.Path path)
    {
        if (path.nodes == null || path.nodes.Length == 0)
        {
            //no path found
            this.FinishWalk();
            return;
        }

        this._baseItem.SetState(Common.State.WALK);

        this._path = path;
        this._currentNodeIndex = 0;
        if (path != null && path.nodes != null && path.nodes.Length > 0)
        {
            this.MoveToPosition(this._path.nodes[0]);
        }
    }

    private void _WalkNextNode()
    {
        if (this._path != null && this._path.nodes != null && this._currentNodeIndex < this._path.nodes.Length - 1)
        {
            this._currentNodeIndex++;
            this.MoveToPosition(this._path.nodes[this._currentNodeIndex]);
            if (this.OnBetweenWalk != null)
            {
                this.OnBetweenWalk.Invoke();
            }
        }
        else
        {
            this.FinishWalk();
        }
    }

    public void CancelWalk()
    {
        this._isWalking = false;
        this._targetPosition = transform.position;
        this.OnFinishWalk = null;
        this.OnBetweenWalk = null;
    }

    public BaseItemScript GetNearestWallOnPath()
    {
        if (this._path != null && this._path.nodes != null && this._path.nodes.Length > 0)
        {

            for (int index = 0; index < this._path.nodes.Length; index++)
            {
                BaseItemScript item = GridManager.instance.GetItemInPosition(this._path.nodes[index]);
                if (item != null && !item.isDestroyed && item.itemData.name == "Wall")
                {
                    return item;
                }
            }
        }

        return null;
    }

    GridManager.Path path1, path2;
    private void OnDrawGizmos()
    {
        if (!EnableGizmos) return;

        Gizmos.color = Color.red;
        if (this._path != null && this._path.nodes != null)
        {
            for (int index = _currentNodeIndex; index < this._path.nodes.Length; index++)
            {
                // if ( index<_path.nodes.Length -2&& Vector3.Distance(_path.nodes[index] - _path.nodes[index + 1] ,_path.nodes[index + 1] - _path.nodes[index + 2]) > .1f)
                // 	Gizmos.DrawSphere(this._path.nodes[index], .2f);
                // Gizmos.DrawWireCube(this._path.nodes[index], Vector3.one * .3f);
                // Gizmos.color = Color.black;
                if (index == _currentNodeIndex)
                    Gizmos.DrawLine(transform.position, _path.nodes[index]);
                else
                    Gizmos.DrawLine(this._path.nodes[index - 1], _path.nodes[index]);
            }
        }

        //Gizmos.color = Color.green;
        //      if (path1 != null && path1.nodes != null)
        //      {
        //          for (int index = 0; index < path1.nodes.Length-1; index++)
        //          {
        //              Gizmos.DrawLine(path1.nodes[index], path1.nodes[index + 1]);
        //          }
        //      }
        //Gizmos.color = Color.yellow;
        //      if (path2 != null && path2.nodes != null)
        //      {
        //          for (int index = 0; index < path2.nodes.Length-1; index++)
        //          {
        //              Gizmos.DrawLine(path2.nodes[index], path2.nodes[index + 1]);
        //          }
        //      }
        // void upsiae()
        // {

        // }
    }
}
